/*
 * Copyright (C) 2014 Lucid Wolf
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.lucidhex.viewer;

import com.lucidhex.hex.LucidIndex;
import com.lucidhex.hex.PlaneCoord;
import java.awt.Dimension;
import java.awt.Point;

/**
 *
 * @author Wolf
 */
public class ViewTransform {
    private double scaleFactor = 1.0;
    private Point panelCenter = null;
    private PlaneCoord viewCenter = null;
    private double theta = 0.0; // radians
 
    public ViewTransform(Dimension size, PlaneCoord viewCenter, double viewRadius, double theta){
        this.viewCenter = viewCenter;
        int width = size.width;
        int height = size.height;
        int pixRad = (int)Math.min(width/2, height/2);
        panelCenter = new Point(width/2, height/2);
        scaleFactor = pixRad/viewRadius;
        this.theta = theta;
    }
    public ViewTransform(LucidIndex ind1, LucidIndex ind2, Point pt1, Point pt2){
        PlaneCoord s1 = new PlaneCoord(ind1);
        viewCenter = s1;
        panelCenter = pt1;
        PlaneCoord s2 = new PlaneCoord (ind2);
        theta = Math.atan2(s2.X()-s1.X(), s2.Y()-s1.Y()) - Math.atan2(pt2.getX()-pt1.getX(), -pt2.getY()+pt1.getY());
        int width = Math.abs(pt2.x-pt1.x);
        int height = Math.abs(pt2.y-pt1.y);
        int pixRad = (int)Math.sqrt(width*width + height*height);
        double viewRadius = Math.sqrt((s1.X()-s2.X())*(s1.X()-s2.X())+(s1.Y()-s2.Y())*(s1.Y()-s2.Y()));
        scaleFactor = pixRad/viewRadius;        
    }
    public int[] transformPoint(PlaneCoord sc){
        int out[] = new int[2];
        // set to stupid world center then scale
        double x = scaleFactor*(sc.X()-viewCenter.X());
        double y = scaleFactor*(sc.Y()-viewCenter.Y());
        // transform rotation
        double xp = Math.round(Math.cos(theta)*x - Math.sin(theta)*y);
        double xy = Math.round(Math.sin(theta)*x + Math.cos(theta)*y);
        // flip y and translate to center pixel
        out[0] = (int)Math.round(xp + panelCenter.getX());
        out[1] = (int)Math.round(-xy + panelCenter.getY());
        return out;
    }
    public PlaneCoord reversetransform(int[] pt){
        double x = pt[0];
        double y = -pt[1];
        x = (x-panelCenter.getX())/scaleFactor;
        y = (y+panelCenter.getY())/scaleFactor;
        double xp = (Math.cos(-theta)*x - Math.sin(-theta)*y);
        double yp = (Math.sin(-theta)*x + Math.cos(-theta)*y);
        xp = xp + viewCenter.X();
        yp = yp + viewCenter.Y();
        return new PlaneCoord(xp,yp);
    }

    public PlaneCoord reverseTransform(Point p) {
        return reversetransform(new int[]{p.x, p.y});
    }    
    public PlaneCoord reverseTransform(int i, int j) {
        return reversetransform(new int[]{i, j});
    }
    public double getScaleFactor() {
        return scaleFactor;
    }
    public double getTheta() {
        return theta;
    }

    
}
